///@brief Implementation of the class representing a point
///@author Arnaud Duval
///@version 0.0
///@date 2010/03/30

#include "../include/Point.h"
#include <cmath>
#include <cassert>
#include <cstring>

///@brief Default constructor
Point::Point()
{
	dim = 0;
}

///@brief Constructor giving space dimension
///@param size space dimension
Point::Point(int size)
{
	coords = new double[size];
	dim = size;
}

///@brief Copy constructor
///@param p Point to copy
Point::Point(const Point &p)
{
	dim = p.dim;
	coords = new double[dim];
	for(unsigned int i = 0 ; i < dim ; i++)
		coords[i] = p.coords[i];
}

///@brief Copy constructor for temporary object
///@param p Pointer to Point to copy
Point::Point(Point* p)
{
	dim = (*p).dim;
	coords = new double[dim];
	for(unsigned int i = 0 ; i < dim ; i++)
		coords[i] = (*p).coords[i];
}

///@brief Destructor
Point::~Point()
{
	if(dim != 0)
		delete[] coords;
}

///@brief return Dimension of used space
unsigned int Point::Dim()
{
	return dim;
}

///@brief return a coordinate
///@param idx Index of returned coordinate
double& Point::Coord(unsigned int idx)
{
    assert(idx > 0);
    assert(idx <= dim);
    return coords[idx-1];
}

///@brief Overload of = operator
///@param p right hand member Point
Point& Point::operator=(const Point &p)
{
	if(dim != 0)
		delete[] coords;
	dim = p.dim;
	coords = new double[dim];
	for(unsigned int i = 0 ; i < dim; i++)
		coords[i] = p.coords[i];
	return (*this);
}


///@brief Overload of = operator for temporary object
///@param p Right hand operand
Point& Point::operator=(Point* p)
{
	dim = (*p).dim;
	coords = new double[dim];
	for(unsigned int i = 0 ; i < dim ; i++)
		coords[i] = (*p).coords[i];
	return (*this);
}

///@brief Overload of &= operator : copy without size check
///@param p Point object to copy
Point& Point::operator&=(const Point & p)
{
	if(!p.dim)
	{
		if(dim)
			delete[] coords;
		dim = 0;
	}
	else
	{
		if(p.dim != dim)
		{
			if(dim)
				delete[] coords;
			coords = new double[dim = p.dim];
		}
		memcpy(coords, p.coords, p.dim*sizeof(double));
	}
	return (*this);
}

///@brief Comput distance between two points
///@param p1 First point
///@param p2 Second point
double Distance(const Point& p1, const Point& p2)
{
	assert(p1.dim == p2.dim);
	double res = 0.;
	for(unsigned int i = 0 ; i < p1.dim ; i++)
	{
		res += pow(p1.coords[i] - p2.coords[i], 2.);
	}
	return sqrt(res);
}

